import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

import 'js_bridge.dart';

class WebPage extends StatefulWidget {
  const WebPage({super.key});

  @override
  State<WebPage> createState() => _WebPageState();
}

class _WebPageState extends State<WebPage> {
  // 1
  late WebViewController controller;
  String message = "init";
  int paramId = 0;
  // JS交互桥接对象
  final JSBridge _jsBridge = JSBridge();

  @override
  void initState() {
    super.initState();
    _initWebView();
    _initJsBridge();

    Future.delayed(const Duration(seconds: 1), () {
      // 需要延时加载，jsBridge 才生效
      controller.loadFlutterAsset("assets/html/index.html");
    });
  }

  _logFlutter(String msg) {
    print(msg);
    setState(() {
      message = msg;
    });
  }

  _initWebView() async {
    // 2
    controller = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      // ..loadRequest(Uri.parse("https://www.baidu.com"))
      // ..loadFlutterAsset("assets/html/index.html")
      // ..loadHtmlString('<a href="/frontend">打开前段页面</a>')
      // ...
      ..addJavaScriptChannel(
        "flutterObj",
        onMessageReceived: (JavaScriptMessage message) {
          _logFlutter("flutterObj, msg: ${message.message}");
          setState(() {
            this.message = message.message;
          });
        },
      )
      ..addJavaScriptChannel(
        JSBridge.name,
        onMessageReceived: (JavaScriptMessage message) {
          _logFlutter("jsbridge, msg: ${message.message}");
          _jsBridge.receiverMessage(message.message);
        },
      )
      ..setNavigationDelegate(NavigationDelegate(
        onUrlChange: (change) {
          // 启动和热加载都会回调 onUrlChange，放在这里注入更合适
          // 注入js,处理相关 Navtive <-> JS 交互
          _jsBridge.injectBridgeJS(controller);
        },
      ));
  }

  _initJsBridge() {
    // 设置执行js的方法
    _jsBridge.messageExecutor = controller.runJavaScript;

    _jsBridge.register("getToken", (data, callback) {
      _logFlutter("getToken $data");
      // 执行回调方法，数据传给js
      Future.delayed(const Duration(seconds: 1), () {
        _logFlutter("getToken callback $data");
        callback("getToken: flutter $data");
      });
    });

    _jsBridge.register("testCallback", (data, callback) {
      _logFlutter("testCallback $data");
    });

    _jsBridge.register("testUserInfoCallBack", (data, callback) {
      _logFlutter("testUserInfoCallBack $data");
    });
  }

  _callJsBridge() {
    _logFlutter("_callJsBridge");
    var param = {"userName": "myName"};
    _jsBridge.call(
      "userInfo",
      param,
      callback: (responseData) {
        _logFlutter("_callJsBridge callback: $responseData");
      },
      errorCallback: (errorMessage) {
        _logFlutter("_callJsBridge error: $errorMessage");
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('WebPage')),
      body: Column(children: [
        ElevatedButton(
          onPressed: () => _runJsOnly(),
          child: const Text("runJavaScript"),
        ),
        ElevatedButton(
          onPressed: () => _runJsWithResult(),
          child: const Text("runJavaScriptReturningResult"),
        ),
        ElevatedButton(
          onPressed: () => _runJsWithParam(),
          child: const Text("runJavaScriptWithParam"),
        ),
        ElevatedButton(
          onPressed: () => _callJsBridge(),
          child: const Text("callJsBridge"),
        ),
        Text(message),
        Expanded(
          child: WebViewWidget(controller: controller),
        )
      ]),
    );
  }

  _runJsOnly() {
    _logFlutter('_runJsOnly');
    controller.runJavaScript('runJsOnly()');
  }

  _runJsWithResult() async {
    String jsStr = "runJsWithResult()";
    var result = await controller.runJavaScriptReturningResult(jsStr);
    _logFlutter("_runJsWithResult js=$jsStr, res=$result");
  }

  _runJsWithParam() async {
    var param = "FlutterParamString${++paramId}";
    String jsStr = "runJsWithParam('$param')";
    var result = await controller.runJavaScriptReturningResult(jsStr);
    _logFlutter("js=$jsStr, res=$result");
  }
}
